﻿using System.Collections.Generic;
using System.Linq;
using Foxit.PDF;
using Foxit.PDF.IO;
using Foxit.PDF.PageElements;
using Sustainalytics.ESG.Entities;
using Sustainalytics.Reporting.Framework;

namespace Sustainalytics.ReportGenerator.BL
{
    public class SustainabilityAndBusinessImpactChart : PageElement
    {
        public float Left { get; set; }
        public float Top { get; set; }
        public float Width { get; set; }
        public float Height { get; set; }
        public bool ShowGridLines { get; set; }
        public List<SubPeerGroupKeyEsgIssue> SubPeerGroupKeyEsgIssues { get; set; }
        public int ChartType { get; set; }

        public SustainabilityAndBusinessImpactChart(float left, float top, float width, float height)
        {
            Left = left;
            Top = top;
            Width = width;
            Height = height;
        }

        private Group Chart()
        {
            var pageElements = new Group();


            var left = Left + 20f;
            var lineSize = 1f;
            var lineColor = RgbColor.Black;

            const float rowCount = 10f;
            const float colCount = 10f;
            const int cellWidth = 35;
            const float cellHeight = 11.5f;

            const float verticalLineHeight = cellHeight * colCount;

            for (var i = 0; i <= rowCount; i++)
            {
                if (i == 0)
                {
                    pageElements.Add(new Line(left, Top, left, Top + verticalLineHeight, lineSize, lineColor));
                }
                if (i > 0)
                {
                    lineSize = 0.2f;

                    if (ShowGridLines)
                    {
                        lineColor = RgbColor.WhiteSmoke;
                        pageElements.Add(new Line(left, Top, left, Top + verticalLineHeight, lineSize, lineColor));
                    }
                }
                if (i == 3 || i == 7)
                {
                    lineSize = 0.2f;
                    lineColor = RgbColor.Silver;
                    pageElements.Add(new Line(left, Top, left, Top + verticalLineHeight, lineSize, lineColor));
                }

                left += cellWidth;
            }

            left = Left + 10f;
            var labelSize = 6f;

            pageElements.Add(
                new Label("High", left, Top + cellHeight * 3, cellHeight * 3, 
                    labelSize + 2f, Fonts.CalibriBold, labelSize, 
                    TextAlign.Center, RgbColor.Black) { Angle = -90 });
            pageElements.Add(
                new Label("Medium", left, Top + cellHeight * 7, cellHeight * 4, 
                    labelSize + 2f, Fonts.CalibriBold, labelSize, 
                    TextAlign.Center, RgbColor.Black) { Angle = -90 });
            pageElements.Add(
                new Label("Low", left, Top + cellHeight * 10, cellHeight * 3,
                    labelSize + 2f, Fonts.CalibriBold, labelSize, 
                    TextAlign.Center, RgbColor.Black) { Angle = -90 });


            left = Left + 20f;
            var top = Top + cellHeight * rowCount;
            var leftOffset = 0.0f;

            const float horizontalLineHeight = cellWidth * colCount;
            lineSize = 1f;
            lineColor = RgbColor.Black;

            for (var i = 0; i < 11; i++)
            {
                if (i == 0)
                {
                    pageElements.Add(
                        new Line(left + leftOffset, top, left + horizontalLineHeight, top, lineSize, lineColor));
                }
                if (i > 0)
                {
                    lineSize = 0.2f;
                    leftOffset = 0.5f;
                    
                    if (ShowGridLines)
                    {
                        lineColor = RgbColor.WhiteSmoke;
                        
                        pageElements.Add(
                            new Line(left + leftOffset, top, left + horizontalLineHeight - leftOffset, top, lineSize,
                                lineColor));
                    }
                }
                if (i == 3 || i == 7)
                {
                    lineColor = RgbColor.Silver;
                    pageElements.Add(
                        new Line(left + leftOffset, top, left + horizontalLineHeight - leftOffset, top, lineSize, lineColor));
                }
                
                top -= cellHeight;
            }
            

            top = Top + cellHeight*rowCount + 5f;

            pageElements.Add(
                new Label("Low", left, top, cellWidth * 3, 
                    labelSize + 2f, Fonts.CalibriBold, labelSize, TextAlign.Center));
            pageElements.Add(
                new Label("Medium", left + cellWidth * 3, top, cellWidth * 4, 
                    labelSize + 2f, Fonts.CalibriBold, labelSize, TextAlign.Center));
            pageElements.Add(
                new Label("High", left + cellWidth * 7, top, cellWidth * 3, 
                    labelSize + 2f, Fonts.CalibriBold, labelSize, TextAlign.Center));

            left = Left + 20f;
            top = Top + cellHeight * rowCount + 15f;
            labelSize = 8f;

            pageElements.Add(
                new Label("Sustainability Impact", Left, Top + cellHeight * 10, cellHeight * 10,
                    labelSize + 2f, Fonts.CalibriBold, labelSize, 
                    TextAlign.Center, RgbColor.Black) { Angle = -90 });

            pageElements.Add(
                new Label("Business Impact", left, top, cellWidth * 10,
                    labelSize + 2f, Fonts.CalibriBold, labelSize,
                    TextAlign.Center, RgbColor.Black));

            RgbColor pointColor;
            var letters = new Dictionary<int, string>
            {
                {0, ""}, {1, "A"}, {2, "B"}, {3, "C"}, {4, "D"}, {5, "E"}, {6, "F"}, {7, "G"}, {8, "H"}, {9, "I"},
                {10, "J"}, {11, "K"}, {12, "L"}, {13, "M"}, {14, "N"}, {15, "O"}, {16, "P"}, {17, "R"}, {18, "S"}, {19, "T"}
            };
            labelSize = 7f;


            for (var sImpact = 0; sImpact < 10; sImpact++)
            {
                for (var bImpact = 0; bImpact < 10; bImpact++)
                {
                    var subPeerGroupKeyEsgIssues = SubPeerGroupKeyEsgIssues.Where(kei => kei.SustainabilityImpact - 1 == sImpact
                        && kei.BussinessImpact - 1 == bImpact).ToList();
                    
                    if (!subPeerGroupKeyEsgIssues.Any()) continue;

                    const int maxBullets = 3;
                    var bulletCount = 0;

                    left = Left + 20 + (bImpact * cellWidth) + (cellWidth / 2);
                    top = Top + cellHeight * 10 - (sImpact * cellHeight) - (cellHeight / 2);

                    if (subPeerGroupKeyEsgIssues.Count == 2)
                        left -= 5;
                    if (subPeerGroupKeyEsgIssues.Count > 2)
                        left -= 9;

                    foreach (var subPeerGroupKeyEsgIssue in subPeerGroupKeyEsgIssues)
                    {
                        if (bulletCount < maxBullets)
                        {
                            pointColor = new RgbColor(91, 97, 100);

                            if (subPeerGroupKeyEsgIssue.ExternalId == 1 && ChartType == 0)
                                pointColor = new RgbColor(65, 177, 166);

                            pageElements.Add(
                                new Circle(left, top, 4f, 4f, pointColor, pointColor, 0.5f, LineStyle.Solid));
                            pageElements.Add(
                                new Label(letters[subPeerGroupKeyEsgIssue.SortKey], left - 4f, top - 3f, 8f,
                                    labelSize + 2f, Fonts.CalibriBold, labelSize,
                                    TextAlign.Center, RgbColor.White));
                            left += 10;
                        }
                        bulletCount++;
                    }
                }
            }

            left = Left + 20 + (10f * cellWidth) + 30f;
            top = Top;
            labelSize = 7f;

            foreach (var subIndustryKeyEsgIssue in SubPeerGroupKeyEsgIssues)
            {
                pointColor = new RgbColor(91, 97, 100);

                if (subIndustryKeyEsgIssue.ExternalId == 1 && ChartType == 0)
                    pointColor = new RgbColor(65, 177, 166);

                pageElements.Add(new Circle(left + 3, top + 3f, 3f, 3f, pointColor, pointColor, 0.5f, LineStyle.Solid));
                pageElements.Add(new Label(letters[subIndustryKeyEsgIssue.SortKey], left, top + 1f, 6f,
                    6f, Fonts.CalibriBold, 5f, TextAlign.Center, RgbColor.White));
                pageElements.Add(new Label(subIndustryKeyEsgIssue.Name, left + 9f, top, 200f,
                    labelSize + 2f, Fonts.CalibriRegular, labelSize, TextAlign.Left, RgbColor.Black));
                
                top += 12;
            }
            

            if (ChartType != 0) return pageElements;

            top = Top + cellHeight * rowCount + 15f;

            pointColor = new RgbColor(65, 177, 166);

            pageElements.Add(new Circle(left + 3, top + 3f, 3f, 3f, pointColor, pointColor, 0.5f, LineStyle.Solid));
            pageElements.Add(new Label("= Key ESG Issues (with Analyst Commentary)", left + 9f, top, 200f,
                labelSize + 2f, Fonts.CalibriRegular, labelSize, TextAlign.Left, RgbColor.Black));

            return pageElements;
        }

        public override void Draw(PageWriter writer)
        {
            var chart = Chart();

            writer.Write_q_(true);
            chart.Draw(writer);
            writer.Write_Q(true);
        }
    }
}
